#include "helper/sqlite/stream/Vector.h"

#include "helper/sqlite/stream/Row.h"
#include "helper/sqlite/stream/Room.h"

namespace helper {
namespace sqlite {
namespace stream {

Vector::Vector(QueryResult & r)
: _result(r)
{
}

Vector::~Vector(){
}

Vector::RowIterator::RowIterator(QueryResult & r)
: _result(r)
, _row(nullptr)
, _index(0)
{
}

Vector::RowIterator::~RowIterator() {
  if(_row != nullptr){
    delete _row;
    _row = nullptr;
  }
}

std::optional<Vector::RowIterator::Item> Vector::RowIterator::next() {
  //precondition
  if(!_result)  return std::nullopt;
  if(_row != nullptr){
    delete _row;
    _row = nullptr;
  }

  _result.next();
  if(!_result) return std::nullopt;

  _row = new Row(_index, _result.columnCount(), _result);
  ++ _index;
  return std::make_optional<Item>(_row);
}




Vector::RoomIterator::RoomIterator(QueryResult & r)
:_result(r)
, _rowid(0)
, _colid(0)
, _room(nullptr)
{
}
Vector::RoomIterator::~RoomIterator() {
  if(_room != nullptr){
    delete _room;
    _room = nullptr;
  }
}

std::optional<Vector::RoomIterator::Item> Vector::RoomIterator::next() {
  //1. precondition
  if(!_result) return std::nullopt; //error 
  if(_room != nullptr) { //clear room
    delete _room;
    _room = nullptr;
  }

  //2. init state 
  if(_rowid == 0 && _colid == 0){  // init state, cursor -> first line; max_col_len
    _result.next();
    if(!_result) return std::nullopt;

    _max_col_len =  _result.columnCount();
  }

  //3. change line case
  if(_colid >= _max_col_len){ //change line 
    _result.next();
    if(!_result) return std::nullopt;

    ++ _rowid;
    _colid = 0;
  }

  //4. something to do each time
  _room = new Room(_rowid, _colid, _max_col_len, _result);
  ++ _colid;
  return std::make_optional<Item>(_room);
}



}//namespace stream
}//namespace sqlite
}//namespace helper
